#include <stdarg.h>
#include <string.h>
#include <stdio.h>

#include "drv_uart.h"

static uint8_t rx3buff[UART3_RX_BUF_SIZE];
static uint8_t tx3buff[UART3_TX_BUF_SIZE];


static const uart_gpio tx_gpio[UART_NUM] = {
	{UART3_TX_PINSOURCE, UART3_TX_PINAF, UART3_TX_PIN, UART3_TX_PORT},
};
	
static const uart_gpio rx_gpio[UART_NUM] = {
	{UART3_RX_PINSOURCE, UART3_RX_PINAF, UART3_RX_PIN, UART3_RX_PORT},
};
	
static const uart_module uart_para_tag[UART_NUM] = {
	{UART_WordLength_8b, UART_StopBits_1, UART_Parity_No, UART_Mode_Rx | UART_Mode_Tx, UART_HWFlowControl_None, 115200, UART3},
}; 


uart_para_t uart_para3 = 
{
	rx3buff, tx3buff, 0, UART3_RX_BUF_SIZE, UART3_TX_BUF_SIZE
};

static const uart_dma uart_tx_dma_para[UART_NUM] = 
{
	{NULL, 0, DMA_Priority_Medium, UART3, DMA1_Channel2},
};

static const uart_dma uart_rx_dma_para[UART_NUM] = 
{
	{rx3buff, UART3_RX_BUF_SIZE, DMA_Priority_Medium, UART3, DMA1_Channel3},
};


/**
* @Description:
* @param none.
* @return none
*/
static void uart_tx_gpio_cfg(void)
{	
	GPIO_InitTypeDef gpio_init;
	const uart_gpio *pgpio = NULL;
    GPIO_StructInit(&gpio_init);
	gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
	gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
	for (pgpio = tx_gpio; pgpio < &tx_gpio[UART_NUM]; pgpio++)
	{
		gpio_init.GPIO_Pin = pgpio->pin;
   		GPIO_PinAFConfig(pgpio->gpio, pgpio->pin_source, pgpio->pin_af);
		GPIO_Init(pgpio->gpio, &gpio_init);	
	}

}

static void uart_rx_gpio_cfg(void)
{
	GPIO_InitTypeDef gpio_init;
	const uart_gpio *pgpio = NULL;
    GPIO_StructInit(&gpio_init);
	gpio_init.GPIO_Mode = GPIO_Mode_IPU;
	gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
	for (pgpio = rx_gpio; pgpio < &rx_gpio[UART_NUM]; pgpio++)
	{
		gpio_init.GPIO_Pin = pgpio->pin;
   		GPIO_PinAFConfig(pgpio->gpio, pgpio->pin_source, pgpio->pin_af);
		GPIO_Init(pgpio->gpio, &gpio_init);	
	}

}

/**
* @Description:
* @param none.
* @return none
*/
static void uart_config(void)
{	
	UART_InitTypeDef uartinit;
	const uart_module *puart = NULL;
	
	for (puart = uart_para_tag; puart < &uart_para_tag[UART_NUM]; puart++)
	{
		uartinit.BaudRate 	= puart->baudrate;
		uartinit.WordLength = puart->wordlength;
		uartinit.StopBits 	= puart->stopbits;
		uartinit.Parity 	= puart->parity;
		uartinit.HWFlowControl = puart->hardwareflowcontrol;
		uartinit.Mode 		= puart->mode;
		UART_Init(puart->uartx, &uartinit);
		
		UART_ITConfig(puart->uartx, UART_IER_RXIDLE, ENABLE);
		UART_Cmd(puart->uartx, ENABLE);
	}
}

static void tx_dma_config(void)
{
    DMA_InitTypeDef dma_init;
	const uart_dma *pdma = NULL;
    DMA_StructInit(&dma_init);

    dma_init.DMA_DIR 				= DMA_DIR_PeripheralDST;
    dma_init.DMA_PeripheralInc 		= DMA_PeripheralInc_Disable;
    dma_init.DMA_MemoryInc 			= DMA_MemoryInc_Enable;
    dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    dma_init.DMA_MemoryDataSize 	= DMA_MemoryDataSize_Byte;
    dma_init.DMA_Mode 				= DMA_Mode_Normal;
    dma_init.DMA_M2M 				= DMA_M2M_Disable;
    dma_init.DMA_Auto_reload 		= DMA_Auto_Reload_Disable;
	for (pdma = uart_tx_dma_para; pdma < &uart_tx_dma_para[UART_NUM]; pdma++)
	{
    	DMA_DeInit(pdma->dma_chx);
	    dma_init.DMA_PeripheralBaseAddr = (uint32_t)&(pdma->uartx->TDR);
	    dma_init.DMA_MemoryBaseAddr		= (uint32_t)pdma->memoryaddr;
    	dma_init.DMA_BufferSize 		= pdma->bufsize;
    	dma_init.DMA_Priority 			= pdma->priority;
    	DMA_Init(pdma->dma_chx, &dma_init);
		UART_DMACmd(pdma->uartx, UART_GCR_DMA, ENABLE);
#ifdef UART_DMA_INI
	DMA_ITConfig(pdma->dma_chx, DMA_IT_TC, ENABLE);
#endif
	}

}

static void rx_dma_config(void)
{
	DMA_InitTypeDef dma_init;
	const uart_dma *pdma = NULL;	
	DMA_StructInit(&dma_init);

    dma_init.DMA_DIR 				= DMA_DIR_PeripheralSRC;
    dma_init.DMA_PeripheralInc 		= DMA_PeripheralInc_Disable;
    dma_init.DMA_MemoryInc 			= DMA_MemoryInc_Enable;
    dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    dma_init.DMA_MemoryDataSize 	= DMA_MemoryDataSize_Byte;
    dma_init.DMA_Mode 				= DMA_Mode_Circular;
    dma_init.DMA_M2M 				= DMA_M2M_Disable;
    dma_init.DMA_Auto_reload 		= DMA_Auto_Reload_Disable;
	for (pdma = uart_rx_dma_para; pdma < &uart_rx_dma_para[UART_NUM]; pdma++)
	{
		DMA_DeInit(pdma->dma_chx);
    	dma_init.DMA_PeripheralBaseAddr = (uint32_t)&(pdma->uartx->RDR);
    	dma_init.DMA_MemoryBaseAddr		= (uint32_t)pdma->memoryaddr;
    	dma_init.DMA_BufferSize 		= pdma->bufsize;
    	dma_init.DMA_Priority 			= pdma->priority;
		DMA_Init(pdma->dma_chx, &dma_init); 
		DMA_ITConfig(pdma->dma_chx, DMA_IT_TC, ENABLE);
		DMA_ITConfig(pdma->dma_chx, DMA_IT_HT, ENABLE);
		DMA_Cmd(pdma->dma_chx, ENABLE);
	}
}

void comsendbuf(DMA_Channel_TypeDef *dmachx, uint8_t *pdata, uint16_t size)
{
	dmachx->CMAR = (uint32_t)pdata;
	dmachx->CNDTR = size;
    DMA_Cmd(dmachx, ENABLE);
}

void myprintf(const char *fmt, ...)
{
	va_list arg;
    va_start(arg, fmt);
    vsprintf((char *)tx3buff ,fmt, arg);
    va_end(arg);
	comsendbuf(uart_tx_dma_para->dma_chx, tx3buff, strlen((char *)tx3buff));
}

/**
* @Description:
* @param none.
* @return none
*/
static void nvic_configuration(void)
{
    NVIC_InitTypeDef nvic_init;
	
#ifdef UART_DMA_INI
	nvic_init.NVIC_IRQChannel 					 = DMA1_Channel2_IRQn;
	nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
	nvic_init.NVIC_IRQChannelSubPriority 		 = 1;
	nvic_init.NVIC_IRQChannelCmd 				 = ENABLE;
	NVIC_Init(&nvic_init);
#endif
	nvic_init.NVIC_IRQChannel 					 = DMA1_Channel3_IRQn;
	nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
	nvic_init.NVIC_IRQChannelSubPriority 		 = 1;
	nvic_init.NVIC_IRQChannelCmd 				 = ENABLE;
	NVIC_Init(&nvic_init);
	nvic_init.NVIC_IRQChannel 					 = UART3_IRQn;
	nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
	nvic_init.NVIC_IRQChannelSubPriority 		 = 2;
	nvic_init.NVIC_IRQChannelCmd 				 = ENABLE;
	NVIC_Init(&nvic_init);
}

/**
* @Description:
* @param none.
* @return none
*/
void bsp_uartinit(void)
{
	uart_gpio_clkopen();
	uart_clkopen();
    RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1, ENABLE);

	uart_tx_gpio_cfg();
	uart_rx_gpio_cfg();
	uart_config();
	tx_dma_config();
	rx_dma_config();
	
	nvic_configuration();
}

